package com.definition.service.impl;

import com.definition.bean.IdSequence;
import com.definition.service.IdSequenceService;
import com.definition.service.IdService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

@Service
@Slf4j
public class IdServiceImpl implements IdService {
    @Autowired
    private IdSequenceService idSequenceService;

    private final Queue<String> idQueue = new ConcurrentLinkedQueue<>();
    private final Object lock = new Object(); // 缓存加载锁

    @Override
    public String nextId() {
        String id = idQueue.poll();
        if (id != null) {
            return id;
        }

        // 队列为空，需要加载缓存
        synchronized (lock) {
            // 双重检查，防止其他线程已经加载
            id = idQueue.poll();
            if (id == null) {
                log.debug("缓存id用尽，重新加载新序列");
                load("orderService");
                id = idQueue.poll();
            }
        }
        return id;
    }

    public void load(String serviceName) {
        log.debug("开始缓存新的id序列");
        // 查询数据库
        IdSequence idSequence = idSequenceService.lambdaQuery()
                .eq(IdSequence::getServiceName, serviceName)
                .one();

        if (idSequence == null) {
            throw new RuntimeException("数据库未初始化序列: " + serviceName);
        }

        int dbLastNo = idSequence.getLastno();
        int highmask = idSequence.getHighmask();
        int step = idSequence.getStep();

        // 更新数据库 lastno，保证原子性（乐观锁）
        idSequence.setLastno(dbLastNo + highmask);
        boolean updated = idSequenceService.updateById(idSequence);
        if (!updated) {
            // 更新失败可能是并发，重新加载一次
            load(serviceName);
            return;
        }

        // 缓存到内存队列
        for (int i = 0; i < highmask; i++) {
            dbLastNo += step;
            idQueue.add(String.format("%032d", dbLastNo)); // 32位 ID
        }

        log.debug("id缓存完成 [{} - {}]", dbLastNo - highmask * step + step, dbLastNo);
    }
}
